package cn.itrip.service;

import cn.itrip.entity.ItripUser;
import cn.itrip.ex.TokenValidationFailedException;
import cn.itrip.utils.MD5;
import cn.itrip.utils.UserAgentUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class TokenServiceImpl implements TokenService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public String generateToken(String agent, ItripUser user) {
//        拼接头
        StringBuffer tokenStr = new StringBuffer(TOKEN_PREFIX);
        boolean isMobile = UserAgentUtil.CheckAgent(agent);
        if (isMobile){
            tokenStr.append("MOBILE-");
        }else {
            tokenStr.append("PC-");
        }
        String md5 = MD5.getMd5(user.getId() + "", 32);
        tokenStr.append(md5).append("-").append(user.getId()).append("-");
        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String time = format.format(now);
        tokenStr.append(time).append("-").append(MD5.getMd5(agent,6));
        return tokenStr.toString();
    }

    @Override
    public void save(String token, ItripUser user) {
        stringRedisTemplate.opsForValue().set(token,JSON.toJSONString(user),SESSION_TIMEOUT,TimeUnit.SECONDS);
    }

    @Override
    public ItripUser load(String token) {
        ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
        if (stringRedisTemplate.hasKey(token)){
            String json = valueOps.get(token);
            ItripUser user = JSON.parseObject(json, ItripUser.class);
            return user;
        }
        return null;
    }

    @Override
    public void delete(String token) {
        stringRedisTemplate.delete(token);
    }

    @Override
    public String replaceToken(String agent, String token) throws TokenValidationFailedException {
        if (!validate(agent,token)){
            throw new TokenValidationFailedException("token无效，不能置换！");
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        String createDate = token.split("-")[3];
        Date now = new Date();
        Long expire = stringRedisTemplate.getExpire(token,TimeUnit.MILLISECONDS);
        Date expireDate = new Date(now.getTime()+expire);
        if (expireDate.getTime() - now.getTime()>REPLACEMENT_PROTECTION_TIMEOUT){
            throw new TokenValidationFailedException("token还在保护期，不能置换！");
        }
        ItripUser user = load(token);
        String newToken = generateToken(agent, user);
        save(newToken,user);
        stringRedisTemplate.expire(token,2,TimeUnit.MINUTES);
        return newToken;
    }

    @Override
    public boolean validate(String agent, String token) {
        if (token == null){
            return false;
        }
        String md5 = MD5.getMd5(agent,6);
        String oldMd5 = token.split("-")[4];
        if (!md5.equals(oldMd5)){
            return false;
        }
        return stringRedisTemplate.hasKey(token);
    }
}
